#include "UEFI.h"
#include "UEFIHeader.h"
#include <map>
#include <codecvt>
#include "Var.h"
#include "VarHeader.h"
#include "ConfigPro.h"

using namespace config;
using namespace EasyJson;

bool bAddItem = false;
string stringtest;
vector<TreeInfo> subTree;
vector<Question> Qid;
TreeInfo SubForm = {0};
JSONObject *CfgJson = NULL;

static const char *GetString(const vector<string> &strings, size_t index)
{
    return strings.size() > index ? strings[index].c_str() : "<invalid offset>";
}

static int SerchSameName(vector<TreeInfo> &VarTree, int FatherId, string name)
{
	int i = 0;
	for (i = (VarTree[FatherId - 1].child - 1); i < VarTree.size(); i++){
		if (VarTree[i].father != FatherId)
			continue;

		if (name ==  VarTree[i].value.name)
		{
			return VarTree[i].child;
		}
	}
	
	return 0;
}

static char *convert_uuid_to_str (EFI_GUID uuid, char *str, int len)
{
  char     *src;
  char     *dst;

  if (!str)
    return NULL;

  memset (str, 0, len);
  //DBG_INFO ("dst: %4.4s\n", str);
  src = (char *)&uuid;
  dst = str;
  sprintf (dst,
           "%02X%02X%02X%02X-%02X%02X-%02X%02X-", 
           *(uint8_t *)(src + 3),
           *(uint8_t *)(src + 2),
           *(uint8_t *)(src + 1),
           *(uint8_t *)(src),
           *(uint8_t *)(src + 5),
           *(uint8_t *)(src + 4),
           *(uint8_t *)(src + 7),
           *(uint8_t *)(src + 6)
          );
  //DBG_INFO ("dst: %16.16s\n", dst);

  src += 8;
  dst += 16 + 3;
  sprintf (dst,
           "%02X%02X-%02X%02X%02X%02X%02X%02X", 
           *(uint8_t *)(src),
           *(uint8_t *)(src + 1),
           *(uint8_t *)(src + 2),
           *(uint8_t *)(src + 3),
           *(uint8_t *)(src + 4),
           *(uint8_t *)(src + 5),
           *(uint8_t *)(src + 6),
           *(uint8_t *)(src + 7)
          );

  //DBG_INFO ("uuid str: %s\n", str);

  return str;
}

/* 判断配置是否应该加入Json树中 */
static bool QuestionObjInt (vector<TreeInfo> &VarTree, const char *name, TreeInfo *FormSet, vector<TreeInfo> &subTree, TreeInfo *FormTree, uint16_t VaribleId, int offset, map<int, vector<EFI_VARIABLE_PACK>> &VarMap, VARIABLE_PACK *variable, vector<string> inVarFile)
{
	uint32_t index = 0, varid = 0,i = 0, u32VarIndex = 0;
	JSONObject tempObj = {0};
	bool bBootOrder = false;
    char buf[128] = {0};
    char tempname[1024]={0};
    string temstr;               
	TreeInfo Vartemp = {0};
	int child = 0, tmpNum = 0;

	if (0 == (*name))
	{
		return false;
	}

	/* 为了避免名字都为N/A,导致在JSON中被替换掉，所以名字后面加offset与以区分 */
	if (memcmp(name, "N/A", sizeof("N/A")))
	{
		snprintf(tempname, sizeof(tempname), "%s", name);
	}
	else
	{
		snprintf(tempname, sizeof(tempname), "%s %d", name, offset);
	}

    if (sscanf(name, "Boot Option #%d", &tmpNum) || sscanf(name, "Boot Option%d", &tmpNum))
	{
		bBootOrder = true;
	}
	
	/* 先寻找配置项对应的Variable */
	for (index = 0; index < subTree.size(); index++)
    {
		if (subTree[index].value.VaribleId == VaribleId)
		{
			break;
		}
    }

	if (index >= subTree.size())
	{  
		return false;
	}
	
	varid = index;

	for (u32VarIndex = 0; u32VarIndex < VarMap.size(); u32VarIndex++)
	{
		/*与配置文件中的variable文件比较，指获取符合配置文件中的variable文件的值 */
		if (NULL != CfgJson)
		{
			JSONArray valarr = {0};
			valarr = CfgJson->get<JSONArray>(CFGVARFILE);
			for (i = 0; i < valarr.getSize(); i++)
			{	
				string JsonStr = valarr.get<string>(i);
				if (inVarFile[u32VarIndex] == JsonStr)
				{
					break;
				}
			}

			if (i == valarr.getSize())
			{
				continue;;
			}
		}
		
		/* 在varible列表中找到对应的Variable */
		for (index = 0; index < VarMap[u32VarIndex].size(); index++)
		{

			/* 变量中的状态为3F，证明这个变量有效 */
			if (VarMap[u32VarIndex][index].variableHeader.State != 0x3f)
			{
				continue;
			}

			//cout<< subTree[varid].value.name<<"var guid "<<subTree[varid].value.guid<<" guid:"<<variablePackages[index].variableHeader.VendorGuid<<endl;
			if (subTree[varid].value.guid != VarMap[u32VarIndex][index].variableHeader.VendorGuid)
			{
				continue;
			}

			for (i = 0; i < VarMap[u32VarIndex][index].variable.name.name.size(); i+=2)
			{
				buf[(i/2)] = *(VarMap[u32VarIndex][index].variable.name.name.c_str() + i);
			}

									
			temstr=buf;
			if ((!temstr.compare(0, subTree[varid].value.name.size(), subTree[varid].value.name)) && (temstr.size() == subTree[varid].value.name.size()))
			{
				*variable = VarMap[u32VarIndex][index].variable;
				
				break;
			}
		}

		if (index < VarMap[u32VarIndex].size())
		{
			break;
		}
	}

	

	/* 如果没有找到则此配置项不显示 */
	if (u32VarIndex >= VarMap.size())
	{  
		//cout<<"WARN:Not Find Var "<<subTree[varid].value.name<<" Var Num:"<<variablePackages.size()<<endl;
		return false;
	}

	if ((NULL != CfgJson) &&  (!bBootOrder))
	{
		tempObj = CfgJson->get<JSONObject>(FormSet->value.name);
		if (tempObj.getSize() == 0)
		{
			return false;
		}

		JSONArray valarr = {0};
		if ("" != SubForm.value.name)
		{
			valarr = tempObj.get<JSONArray>(SubForm.value.name);
		}
		else
		{
			valarr = tempObj.get<JSONArray>(FormTree->value.name);
		}
		
		string TempStr = tempname;
		for (i = 0; i < valarr.getSize(); i++)
		{	
			string JsonStr = valarr.get<string>(i);
			if (TempStr == JsonStr)
			{
				break;
			}
		}

		if (i == valarr.getSize())
		{
			return false;
		}
	}
	else if ((NULL != CfgJson) &&  (bBootOrder))
	{
		int bbotorder = 0;
		bbotorder = CfgJson->get<int>(BOOTORDERSHOW);
		if (0 == bbotorder)
		{
			return false;
		}
	}

	/* 如果这个页框还没加入到Json树中，则先加入页框 */
	FormSet->child = SerchSameName(VarTree, FormSet->father, FormSet->value.name);
	if (FormSet->child == 0)
	{
		FormSet->child = VarTree.size() + 2;
		VarTree.push_back(*FormSet);
	}

	/* 页框和页面不一致的情况下，再加入页面 */
	if (FormSet != FormTree)
	{
		FormTree->father = FormSet->child - 1;

		FormTree->value.CfgFlag = true;

		/* 页面的名字应为最靠近配置项的页面名字 */
		if ("" != SubForm.value.name)
		{
			FormTree->value.name = SubForm.value.name;
		}
		
		/* 如果再JSON结构中没有对应的页面存在，则加入页面 */
		FormTree->child = SerchSameName(VarTree, FormTree->father, FormTree->value.name);
		if (FormTree->child == 0)
		{
			FormTree->child = VarTree.size() + 2;
			VarTree.push_back(*FormTree);
		}
	}

	child = FormTree->child;
	VarTree[FormTree->child - 2].value.CfgList.add((string)tempname);

	/* 将变量加入到Json树中 */
	subTree[varid].father = child - 1;
	subTree[varid].child = SerchSameName(VarTree, subTree[varid].father, subTree[varid].value.name);
	if (subTree[varid].child == 0){
		subTree[varid].child = VarTree.size() + 2;
		VarTree.push_back(subTree[varid]);
	}
	
	/* 最后加入配置项 */
	Vartemp.father = subTree[varid].child - 1;
	Vartemp.child = 0;
	Vartemp.value.valoption.clear();
	Vartemp.value.name = tempname;
	Vartemp.value.VaribleId = VaribleId;
	Vartemp.value.offset =  offset;

	if (bBootOrder)
	{
		VarTree[FormSet->child - 2].value.bbootorder =  true;
		VarTree[FormTree->child - 2].value.bbootorder =  true;
		VarTree[subTree[varid].child - 2].value.bbootorder =  true;
		Vartemp.value.bbootorder =  true;
	}

	VarTree.push_back(Vartemp);
	bAddItem = true;      
	return true;
		
}

/* 从variable列表中找到对应名字的variable */
bool findVarPack(VaribleInfo var, const vector<EFI_VARIABLE_PACK> &variablePackages, VARIABLE_PACK **variable)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr;
	
	for (index = 0; index < variablePackages.size(); index++)
	{
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		if (var.guid != variablePackages[index].variableHeader.VendorGuid)
		{
			continue;
		}
			
		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}
								
		temstr=buf;
			
		if ((!temstr.compare(0, var.name.size(), var.name)) && (temstr.size() == var.name.size()))
		{
			*variable = (VARIABLE_PACK *)&variablePackages[index].variable;
		
			break;
		}
	}

	if (index >= variablePackages.size())
	{  
		return false;
	}

	return true;
}

/* 根据配置内容替换Variable列表中的值 */
int VarConfig :: ReplaceVar (VaribleInfo VarInfo, JSONObject *ConfigObj, vector<VARIABLE_PACK *> &VariblePackage)
{
	uint32_t num = 0, i = 0;
	uint64_t val = 0, u64temp;
	char *buf = NULL;
	uint8_t *ptr = NULL;
	string tempstr;
	uint32_t u32offset;

	u32offset = VarInfo.offset;

	if (VarInfo.type == NUM)
	{
		if (VarInfo.size > 4)
		{
			num = (uint32_t)ConfigObj->get<int>(VALUE_H);
			val = ((uint64_t)num << 32);
		}

		num = (uint32_t)ConfigObj->get<int>(VALUE_L);
		val += num;

		if (val == VarInfo.val)
		{
			goto end;
		}

		if ((val < VarInfo.min) || (val > VarInfo.max))
		{
			printf("\033[41;5m%s input err %u %u %u %u\033[0m\r\n", VarInfo.name.c_str(), val, VarInfo.min, VarInfo.max, VarInfo.offset);
			goto end;
		}

		for (i = 0; i < VarInfo.valoption.size(); i++)
		{
			if (val == VarInfo.valoption[i])
			{
				break;
			}
		}

		if ((i == VarInfo.valoption.size()) && (0 != VarInfo.valoption.size()))
		{
			printf("\033[41;5m%s %d is invalid value %d.\033[0m\n", VarInfo.name.c_str(), val, VarInfo.valoption.size());
			goto end;
		}


		if (VarInfo.bbootorder)
		{
			if (BootOrderVaild(val, VarInfo, VariblePackage))
			{
				printf("\033[41;5mthe BootNum %d already exists.\033[0m\n", VarInfo.val);
				return 1;
			}
		}

		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			u64temp = val;
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			for (i = 0; i < VarInfo.size; i++)
			{
				*(ptr + i) = (uint8_t)u64temp;
				u64temp = (u64temp >> 8);
			}
		}
	}
	else if (VarInfo.type == CHECK)
	{
		/* check类型只有1和0 */
		val = ConfigObj->get<int>(CHECKBOX);
		if (val > 1)
		{
			cout <<VarInfo.name<<" input err Check: "<<val<<endl;
			return 1;
		}
		
		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			u64temp = val;
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			for (i = 0; i < VarInfo.size; i++)
			{
				*(ptr + i) = (uint8_t)u64temp;
				u64temp = (u64temp >> 8);
			}
		}
	}
	
	else if (VarInfo.type == DATE)
	{
		val = ConfigObj->get<int>(DAY);
		val = (val << 8);
		
		val += ConfigObj->get<int>(MONTH);
		val = (val << 16);
		
		val += ConfigObj->get<int>(YEAR);
		
		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			u64temp = val;
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			for (i = 0; i < 4; i++)
			{
				*(ptr + i) = (uint8_t)u64temp;
				u64temp = (u64temp >> 8);
			}
		}
	}
	else if (VarInfo.type == TIME)
	{
		val = (val << 8);
		
		val += ConfigObj->get<int>(SECOND);
		val = (val << 8);
		
		val += ConfigObj->get<int>(MINUTE);
		val = (val << 8);
		
		val += ConfigObj->get<int>(HOUR);
		
		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			u64temp = val;
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			for (i = 0; i < 4; i++)
			{
				*(ptr + i) = (uint8_t)u64temp;
				u64temp = (u64temp >> 8);
			}
		}
	}
	else if (VarInfo.type == LIST)
	{
		JSONArray valarr;
		valarr = ConfigObj->get<JSONArray>(LISTVAL);

		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			for (i = 0; i < valarr.getSize(); i++)
			{
				*(ptr + i) = valarr.get<int>(i);
				//cout << valarr.get<int>(i) <<endl;
			}
		}
	}
	else
	{
		tempstr = ConfigObj->get<string>(VALUE_L);

		if ((0 != tempstr.size()) && ((2 * tempstr.size() > VarInfo.size) || (tempstr.size() < VarInfo.min) || (tempstr.size() > VarInfo.max)))
		{
			cout <<VarInfo.name<<" Err Size:"<<tempstr.size()<<endl;
			return 0;
		}


		for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
		{
			ptr = &VariblePackage[u32VarIndex]->data.data[u32offset];
			/* 字符串需要将窄字符变为宽字符 */
			for (i = 0; i < tempstr.size(); i++)
			{
					*(ptr + i * 2) = *(tempstr.c_str() + i);
					*(ptr + i * 2 + 1) = 0x00;
			}

			for (i = 2 * tempstr.size(); i < VarInfo.size; i++)
			{
					*(ptr + i) = 0x00;
			}
		}
	}

	return 0;

end:
	if (VarInfo.bbootorder)
	{
		if (BootOrderVaild(VarInfo.val, VarInfo, VariblePackage))
		{
			printf("\033[41;5mthe BootNum %d already exists.\033[0m\n", VarInfo.val);
			return 1;
		}
	}

	return 0;
}

/* 生成Json结构 */
void VarConfig :: CreateJson (int index)
{		
	int i = 0;

	if (index >= VarTree.size())
			return;

	if (0 == VarTree[index].child)
	{
		if (bShow)
		{
			printf("%s:\r\n", VarTree[index].value.name.c_str());
			printf("Help:%s\r\n", VarTree[index].value.obj.get<string>(HELP).c_str());
			printf("Tips:%s\r\n", VarTree[index].value.obj.get<string>(TIP).c_str());
			if (VarTree[index].value.type == NUM)
			{
				uint64_t val = 0;
				if (VarTree[index].value.size > 4)
				{
					val = (((uint64_t)VarTree[index].value.obj.get<unsigned int>(VALUE_H)) << 32);
				}
				
				val += (uint32_t)VarTree[index].value.obj.get<unsigned int>(VALUE_L);
				printf("Value:%lu\r\n", val);
			}
			else if (VarTree[index].value.type == CHECK)
			{
				printf("Value:%lu\r\n", VarTree[index].value.obj.get<int>(CHECKBOX));
			}
			else if (VarTree[index].value.type == LIST)
			{
				JSONArray valarr;
				valarr = VarTree[index].value.obj.get<JSONArray>(LISTVAL);
				for (i = 0; i < valarr.getSize(); i++)
				{
					if (i == 0)
					{
						printf("Value:%lu", valarr.get<int>(i));
					}
					else
					{
						printf(" %lu", valarr.get<int>(i));
					}
					//cout << valarr.get<int>(i) <<endl;
				}
				
				if (i != 0)
				{
					printf("\r\n");
				}
			}
			else
			{
				printf("Value:%s\r\n", VarTree[index].value.obj.get<string>(VALUE_L).c_str());
			}
		}

		return;
	}
	for (i = (VarTree[index].child - 1); i < VarTree.size(); i++){
		if (VarTree[i].father != (index + 1))
			continue;
				
		CreateJson (i);
		VarTree[index].value.obj.add(VarTree[i].value.name, VarTree[i].value.obj);
	}

	return;
}

/* 生成Json结构 */
void VarConfig :: CfgFileInitial (int index)
{		
	int i = 0;

	if (index >= VarTree.size())
			return;
	if (0 == VarTree[index].child)
	{
		return;
	}
	/* 页框下面的内容已添加到CfgList，就不继续解析了 */
	if (VarTree[index].value.CfgFlag)
			return;
	
	for (i = (VarTree[index].child - 1); i < VarTree.size(); i++){
		if ((VarTree[i].father != (index + 1)))
			continue;	

		CfgFileInitial (i);
		
		if (VarTree[i].value.CfgFlag)
		{
			VarTree[index].value.obj.add(VarTree[i].value.name, VarTree[i].value.CfgList);
		}
		else 
		{
			VarTree[index].value.obj.add(VarTree[i].value.name, VarTree[i].value.obj);
		}
	}

	return;
}

/* 生成只有BootOrder的Json结构 */
void VarConfig :: CreateBootOrderJson (int index)
{		
	int i = 0;

	if (index >= VarTree.size())
			return;

	if (0 == VarTree[index].child)
			return;
	for (i = (VarTree[index].child - 1); i < VarTree.size(); i++){
		if ((VarTree[i].father != (index + 1)) || (false == VarTree[i].value.bbootorder))
		{
			continue;
		}
			
		CreateBootOrderJson (i);
		VarTree[index].value.obj.add(VarTree[i].value.name, VarTree[i].value.obj);
	}

	return;
}

/* 如果在配置文件中不存在的启动顺序与配置文件中的启动顺序重复，则修正配置文件中不存在的启动顺序 */
int VarConfig :: FixBootOder (uint64_t NewVal, VaribleInfo VarInfo, vector<VARIABLE_PACK *> &VariblePackage)
{
	int i = 0;
	int index = 0;
	uint8_t *ptr = NULL;

	while (index < BootValTree.size())
	{
		for (i = 0; i < BootValTree.size(); i++)
		{
			if (BootValTree[i].NewVal == NewVal)
			{
				NewVal = BootValTree[i].VarInfo.val;
				index++;
				break;
			}
		}

		if 	(i == BootValTree.size())
		{
			break;
		}
	}

	if (index == BootValTree.size())
	{
		printf("not find suitable boot order\r\n");
		return 1;
	}

	for (uint32_t u32VarIndex = 0; u32VarIndex < VariblePackage.size(); u32VarIndex++)
	{
		ptr = &VariblePackage[u32VarIndex]->data.data[VarInfo.offset];
		for (i = 0; i < VarInfo.size; i++)
		{
			*(ptr + i) = (uint8_t)NewVal;
			NewVal = (NewVal >> 8);
		}
	}

	return 0;
}

/* 添加bootorder的值，对比是否有重复启动项  */
int VarConfig :: BootOrderVaild(uint64_t NewVal, VaribleInfo VarInfo, vector<VARIABLE_PACK *> &VariblePackage)
{
	int i = 0;
	BootVal BootVal;
	uint64_t value = 0;

	/* 为0xff表示这个启动项没有在config里，但是存在vfr里 */
	if (NewVal == 0xFF)
	{
		value = VarInfo.val;
	}
	else
	{
		value = NewVal;
	}

	for (i = 0; i < BootValTree.size(); i++)
	{
		if (BootValTree[i].VarInfo.offset == VarInfo.offset)
		{
			return 0;
		}
	}

	for (i = 0; i < BootValTree.size(); i++)
	{
		if (BootValTree[i].NewVal == value)
		{
			if (NewVal == 0xFF)
			{
				return FixBootOder (BootValTree[i].VarInfo.val, VarInfo, VariblePackage);
			}
			else
			{
				return 1;
			}
			
		}
	}

	if (NewVal != 0xFF)
	{
		BootVal.VarInfo = VarInfo;
		BootVal.NewVal = value;
		BootValTree.push_back(BootVal);
	}

	return 0;
}

/* 该函数主要是遍历所有配置，替换variable */
int VarConfig :: FindVar (int index, JSONObject *ConfigObj, map<int, vector<EFI_VARIABLE_PACK>> &VarMap)
{		
	int i = 0, ret = 0;
	JSONObject tempObj = {0};
	VARIABLE_PACK *variable = NULL;
	vector<VARIABLE_PACK *> Varpackages;
	
	if (index >= VarTree.size())
		return 0;

	if (0 == VarTree[index].child)
		return 0;
	
	/* 如果该层结构是variable的内容，需要从varible列表中找到Variable信息 */
	Varpackages.clear();
	if (VarTree[index].value.varFlag)
	{
		BootValTree.clear();
		for (uint32_t u32VarIndex = 0; u32VarIndex < VarMap.size(); u32VarIndex++)
		{
			if (findVarPack(VarTree[index].value, VarMap[u32VarIndex], &variable))
			{
	        	Varpackages.push_back(variable);
			}
		}
		
	}
	
	/* 搜索配置的子节点 */
	for (i = (VarTree[index].child - 1); i < VarTree.size(); i++){
		if (VarTree[i].father != (index + 1))
			continue;

		/* 寻找配置中的JSON子结构 */
		if (ConfigObj->getSize() != 0)
		{
			tempObj = ConfigObj->get<JSONObject>(VarTree[i].value.name);
		}

		if (tempObj.getSize() == 0)
		{
			if ((Varpackages.size() > 0) && (VarTree[i].value.bbootorder))
			{
				ret = BootOrderVaild(0xff, VarTree[i].value, Varpackages);
				if (0 != ret)
				{
					return ret;
				}
			}

			continue;
		}

		ret = FindVar (i, &tempObj, VarMap);
		if (ret != 0)
			return ret;

		/* 如果已经找到对应的Varible信息，则需要将配置替换 */
		if ((Varpackages.size() > 0) && (tempObj.getSize() != 0))
		{
			ret = ReplaceVar(VarTree[i].value, &tempObj, Varpackages);
			if (ret != 0)
				return ret;
		}
	}

	return ret;
}

int VarConfig :: ParseConfig (const string &InputFile, map<int, vector<EFI_VARIABLE_PACK>> &VarMap)
{		
	ifstream in(InputFile.c_str(), std::ios::binary);
	streampos ps;
	string configstring;
	int FileSize = 0;
	char *buf = NULL;
	
	/* 打开配置文件获取配置内容 */
	in.seekg(0, ios::end);
	ps = in.tellg();
	FileSize = (int)ps;
	in.seekg(0, std::ios::beg);
	if (!in.is_open())
	{
		cout<<"open file err"<<endl;
		return 1;
	}
	
	buf = (char *)calloc(1, FileSize+1);

	in.read(buf, FileSize);
	configstring = buf;

	/* 获取内容的JSON结构 */
	auto *b = dynamic_cast<JSONObject *>(JSONBase::parse(configstring));
	if (NULL == b || b->getSize() == 0)
	{
		cout<<"config is null"<<endl;
		in.close();
		free(buf);
		return 1;
	}

	if (FindVar (0, b, VarMap))
	{
		free(b);
		in.close();
		free(buf);
		return 1;
	}

	free(b);
	in.close();
	free(buf);
	return 0;
}

/* 获取数值的范围 */
void GetValueRange (VaribleInfo *varinfo, uint64_t min, uint64_t max, int len, char* buf)
{
	snprintf(buf, len, "Min: %0llu, Max:%0llu;", min, max);
	varinfo->max = max;
	varinfo->min = min;
	return;
}

/* 获取variable的数值 */
int GetValue (int size, uint64_t MaxSize, array<uint8_t, VARIABLE_MAX_LEN> &VarData, int Offset, int *outsize)
{		
	int value = 0, i = 0;

	if ((uint64_t)(Offset + size) > MaxSize)
	{
		return value;
	}

	/* Variable is the big end */
	for (i = 0; i < size; i++){
		value = (value << 8);
		value += (VarData[Offset + size - i - 1]);
	}

	*outsize = size;

	return value;
}

/* 获取字符串的内容 */
char* GetVarString (int size, uint64_t MaxSize, array<uint8_t, VARIABLE_MAX_LEN> &VarData, int Offset, int *outsize)
{		
	char *buf = NULL;
	int i = 0;

	if ((uint64_t)(Offset + size * 2) > MaxSize)
	{
		return buf;
	}

	buf = (char *)calloc(size, sizeof(char));

	for (i = 0; i < size; i++){
		buf[i] = (VarData[Offset +  i * 2]);
	}

	*outsize = size * 2;

	return buf;
}

/* 判断配置是否有效，如果最大值和最小值是一样的，根本无法配置，就不显示 */
bool ParisVaild (EFI_IFR_NUMERIC *UefiNum)
{
	bool Vaild = true;
	if ((((UefiNum->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_1) && (UefiNum->data.u8.MinValue == UefiNum->data.u8.MaxValue)) || 
		(((UefiNum->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_2) && (UefiNum->data.u16.MinValue == UefiNum->data.u16.MaxValue)) ||
		(((UefiNum->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_4) && (UefiNum->data.u32.MinValue == UefiNum->data.u32.MaxValue)) ||
		(((UefiNum->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_8) && (UefiNum->data.u64.MinValue == UefiNum->data.u64.MaxValue))) {
		
		Vaild = false;            	
	}

	return Vaild;
}

/* 从页面列表中找到对应页面 */
TreeInfo *FindForm(vector<TreeInfo> &FormTree, uint16_t FormId, string name)
{
	uint32_t i = 0;
	for (i = 0; i < FormTree.size(); i++)
	{
		if (FormTree[i].value.FormId == FormId)
		{
			FormTree[i].value.name = name;
			return &FormTree[i];
		}
	}

	return NULL;
}
vector<uint8_t> idStack;
uint8_t idTabs;

void InText(uint8_t reason)
{
	// Increment number of tabs
	idTabs++;

	// Add to conditional stack
	idStack.push_back(reason);
}

/* 对disableif选项解析，用于禁用某些显示 */
void getinvaildId(vector<Question> &Qid, const vector<UEFI_IFR_STRING_PACK> &stringPackages, const vector<UEFI_IFR_FORM_SET_PACK> &formSets, const string &buffer, const vector<string> &strings, map<int, vector<EFI_VARIABLE_PACK>> &VarMap) {

   uint8_t index;
   bool disable = false; 
   bool disbletrue = false;
   vector<TreeInfo> subTree;
   uint32_t varid = 0, idindex = 0, u32VarPackIndex = 0;
   string temstr; 
   uint32_t u32VarIndex = 0;
   VARIABLE_PACK variabletemp;
   int size = 0;
   string name;

   subTree.clear();

    // Go through form sets
    for (uint32_t i = 0; i < formSets.size(); i++) {

        uint32_t strPackageOffset = stringPackages[formSets[i].usingStringPackage].structureOffset;

        // Go through all the form set's operations
        for (uint32_t j = formSets[i].header.offset + 4; j < formSets[i].header.offset + formSets[i].header.length; j += static_cast<unsigned char>(buffer[j + 1]) & 0x7F) {

			if (!(static_cast<unsigned char>(buffer[j + 1]) & 0x7F))
			{
				break;
			}
            index++;
			if (index > 10)
			{
				index = 0;
			}

            if (buffer[j] == EFI_IFR_END_OP) {
                // Decrement number of tabs
                idTabs--;
            }
			else if (buffer[j] == EFI_IFR_FORM_SET_OP) {

                // Create temp
                EFI_IFR_FORM_SET *temp = (EFI_IFR_FORM_SET*)&buffer[j];

                // Display temp
                name = GetString(strings, temp->FormSetTitle + strPackageOffset);
            }
            else if (buffer[j] == EFI_IFR_NUMERIC_OP) {

                // Create temp
                EFI_IFR_NUMERIC *temp = (EFI_IFR_NUMERIC*)&buffer[j];
				int value = 0;
				char buf[128] = {0};
				Question tempQ;
				int index1 = 0;
				
				
				if ((disable) && (disbletrue))
				{
					/*获取qestionID用于判断*/
					tempQ.Id = temp->Question.QuestionId;
					tempQ.name = name;
					
					/* 先寻找配置项对应的Variable */
					for (idindex = 0; idindex < subTree.size(); idindex++)
					{
						if (subTree[idindex].value.VaribleId == temp->Question.VarStoreId)
						{
							break;
						}
					}

					if (idindex < subTree.size())
					{  
						varid = idindex;
						
						for (u32VarIndex = 0; u32VarIndex < VarMap.size(); u32VarIndex++)
						{
							/* 在varible列表中找到对应的Variable */
							for (idindex = 0; idindex < VarMap[u32VarIndex].size(); idindex++)
							{
								/* 变量中的状态为3F，证明这个变量有效 */
								if (VarMap[u32VarIndex][idindex].variableHeader.State != 0x3f)
								{
									continue;
								}

								if (subTree[varid].value.guid != VarMap[u32VarIndex][idindex].variableHeader.VendorGuid)
								{
									continue;
								}

								for (index1 = 0; index1 < VarMap[u32VarIndex][idindex].variable.name.name.size(); index1+=2)
								{
									buf[(index1/2)] = *(VarMap[u32VarIndex][idindex].variable.name.name.c_str() + index1);
								}
					
								temstr=buf;
					
								if ((!temstr.compare(0, subTree[varid].value.name.size(), subTree[varid].value.name)) && (temstr.size() == subTree[varid].value.name.size()))
								{
									variabletemp = VarMap[u32VarIndex][idindex].variable;
									break;
								}
							}

							if (idindex < VarMap[u32VarIndex].size())
							{
								u32VarPackIndex = u32VarIndex;
								break;
							}
						}
						
						tempQ.value = 0;
						if (u32VarIndex < VarMap.size())
						{
							if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_1) {
							value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &size);
							}
							else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_2) {
								value = GetValue(2, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &size); 
							}
							else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_4) {
								value = GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &size); 
							}
							else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_8) {
								value = GetValue(4, variabletemp.data.size,  variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 4, &size); 
								tempQ.value = (value << 32);
								value = GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &size);
							}

							tempQ.value |= value;

						}
					}
					
					Qid.push_back(tempQ);

				}
            }
            
            else if (buffer[j] == EFI_IFR_DISABLE_IF_OP) {
				index = 0;
				disable = true;
        
            }
            else if (buffer[j] == EFI_IFR_END_OP) {

                // Create temp
                EFI_IFR_END *temp = (EFI_IFR_END*)&buffer[j];

                // Get condition
                uint8_t condition = idStack.back();

				idStack.pop_back();

				 if (condition == CONDITION)
				{
					disable = false;
					disbletrue = false;
				}
            }
            else if (buffer[j] == EFI_IFR_TRUE_OP) {

               if ((index == 1) && (disable))
			   {
				   disbletrue = true;
			   }
			   else
			   {
				   disable = false;
			   }
            }
			else if (buffer[j] == EFI_IFR_VARSTORE_OP) {

                // Create temp	
				EFI_IFR_VARSTORE *temp = (EFI_IFR_VARSTORE*)&buffer[j];
				TreeInfo Vartemp;
				char   g_uuid_str[37] = { 0 };
		
				convert_uuid_to_str (temp->Guid, g_uuid_str, sizeof(g_uuid_str));
				Vartemp.value.guid = g_uuid_str;

				Vartemp.father = 0;
				Vartemp.child = 0;
				Vartemp.value.varFlag = true;
				Vartemp.value.name = (char *)temp->Name;
				Vartemp.value.VaribleId = temp->VarStoreId;
				subTree.push_back(Vartemp);
          	}
			else if (buffer[j] == EFI_IFR_VARSTORE_EFI_OP)
			{
				EFI_IFR_VARSTORE_EFI *temp = (EFI_IFR_VARSTORE_EFI*)&buffer[j];
				TreeInfo Vartemp;
				char   g_uuid_str[37] = { 0 };
		
				convert_uuid_to_str (temp->Guid, g_uuid_str, sizeof(g_uuid_str));
				Vartemp.value.guid = g_uuid_str;
			
				Vartemp.father = 0;
				Vartemp.child = 0;
				Vartemp.value.varFlag = true;
				Vartemp.value.name = (char *)temp->Name;
				Vartemp.value.VaribleId = temp->VarStoreId;
				subTree.push_back(Vartemp);
			}
        

            EFI_IFR_OP_HEADER *opHdr = (EFI_IFR_OP_HEADER*)&buffer[j];
            if (opHdr->Scope) {
                if (opHdr->OpCode == EFI_IFR_FORM_OP)
                    InText(FORM);
                else if (opHdr->OpCode == EFI_IFR_ONE_OF_OP)
                    InText(OPTION);
                else if (opHdr->OpCode == EFI_IFR_SUPPRESS_IF_OP || opHdr->OpCode == EFI_IFR_NO_SUBMIT_IF_OP || opHdr->OpCode == EFI_IFR_INCONSISTENT_IF_OP || opHdr->OpCode == EFI_IFR_GRAY_OUT_IF_OP || opHdr->OpCode == EFI_IFR_DISABLE_IF_OP || opHdr->OpCode == EFI_IFR_WARNING_IF_OP)
                    InText(CONDITION);
                else if (opHdr->OpCode == EFI_IFR_FORM_SET_OP)
                    InText(FORM_SET);
                else
                    InText(OTHER);
            }
        }
    }
}

void VarConfig :: FindFormTitle(uint32_t id, uint32_t Tid, vector<TreeInfo> &FormTree,  string &FormSetname, const vector<UEFI_IFR_STRING_PACK> &stringPackages, const vector<UEFI_IFR_FORM_SET_PACK> &formSets, const string &buffer, const vector<string> &strings, map<int, vector<EFI_VARIABLE_PACK>> &VarMap, vector<string> inVarFile) {

	bool bdisplay = true;
	bool bdiable = false;
	bool bForm = true;
	bool bSuppress = false;
	bool bstatus = 0;
	uint8_t u8statusIndex = 0;
	VARIABLE_PACK variabletemp;
	TreeInfo *Form = 0;
	UINT16 DisableIfCount = 0;
	UINT16 SuppressIfCount = 0;
	uint64_t value[2] = {0};
	uint8_t valueIndex = 0;
	bool question = false;
	bool eql = false;
	uint8_t startoption = 0xff;
	uint16_t refqId = 0x0;
	uint64_t refqValue = 0x0;

		
    subTree.clear();
	stringtest.clear();
    // Go through form sets
	uint32_t strPackageOffset = stringPackages[formSets[id].usingStringPackage].structureOffset;

	// Go through all the form set's operations
	for (uint32_t j = formSets[id].header.offset + 4; j < formSets[id].header.offset + formSets[id].header.length; j += static_cast<unsigned char>(buffer[j + 1]) & 0x7F) {
		
		
		if (buffer[j] == EFI_IFR_END_OP) {
			// Decrement number of tabs
			numberOfTabs--;
		}
		// Check opcodes

       
		if (buffer[j] == EFI_IFR_FORM_OP) {

                // Create temp
                string name;
				TreeInfo tempTree = {0};
                EFI_IFR_FORM *temp = (EFI_IFR_FORM*)&buffer[j];
				tempTree.father = 0;
				tempTree.child = 0;
				tempTree.value.name = GetString(strings, temp->FormTitle + strPackageOffset);
				name = tempTree.value.name;
				tempTree.value.FormId = temp->FormId;
				SubForm.value.name = "";
				if (0 != name.size())
				{
					if (FormTree[Tid].value.FormId == tempTree.value.FormId)
					{
						//由于goto添加的页面是按ID的，跟实际的名字有区别，所以需要重新对名字赋值
						FormTree[Tid].value.name = tempTree.value.name;
						Form = &FormTree[Tid];
					}
					else
					{
						Form = NULL;
					}
				}				
            }
			else if (buffer[j] == EFI_IFR_SUBTITLE_OP) {

                // Create temp
                EFI_IFR_SUBTITLE *temp = (EFI_IFR_SUBTITLE*)&buffer[j];
				string name;
				name = GetString(strings, temp->Statement.Prompt + strPackageOffset);
				if (("" != name) && (" " != name))
				{
					SubForm.value.name = name;
				}
            }
            else if (buffer[j] == EFI_IFR_ONE_OF_OP) {

                // Create temp
				char buf[64];
                uint32_t value = 0;
                EFI_IFR_ONE_OF *temp = (EFI_IFR_ONE_OF*)&buffer[j];
				const char *szBuf = GetString(strings, temp->Question.Header.Prompt + strPackageOffset);
				if ((NULL != Form) && bdisplay && ParisVaild ((EFI_IFR_NUMERIC*)&buffer[j]) &&
				     QuestionObjInt (VarTree, szBuf, &FormTree[0], subTree, Form, 
										                      temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
				{
					
					if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_1) {
						GetValueRange (&VarTree.back().value, temp->data.u8.MinValue, temp->data.u8.MaxValue, sizeof(buf), buf);
						value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_2) {
						GetValueRange (&VarTree.back().value, temp->data.u16.MinValue, temp->data.u16.MaxValue, sizeof(buf), buf);
						value = GetValue(2, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size); 
					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_4) {
						GetValueRange (&VarTree.back().value, temp->data.u32.MinValue, temp->data.u32.MaxValue, sizeof(buf), buf);
						value = GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size); 
					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_8) {
						GetValueRange (&VarTree.back().value, temp->data.u64.MinValue, temp->data.u64.MaxValue, sizeof(buf), buf);
						value = GetValue(4, variabletemp.data.size,  variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 4, &VarTree.back().value.size); 
						VarTree.back().value.obj.add(VALUE_H, value);
						VarTree.back().value.val = (value << 32);
						value = GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
						VarTree.back().value.size = 8;
					}

					if (strstr(szBuf, "Boot Option #1") || strstr(szBuf, "Boot Option1"))
					{
						bBootOrder = true;
						VarTree.back().value.firstBoot = true;
					}

					startoption = OPTION;
					VarTree.back().value.type = NUM;
				    VarTree.back().value.obj.add(HELP, (const string&)GetString(strings, temp->Question.Header.Help + strPackageOffset));
					VarTree.back().value.obj.add(VALUE_L, value);
					//VarTree.back().value.obj.add("offset", VarTree.back().value.offset);
					stringtest = buf;
					VarTree.back().value.val |= value;	
				}               
            }
			
			else if (buffer[j] == EFI_IFR_CHECKBOX_OP) {

                // Create temp
                int value = 0;
                EFI_IFR_CHECKBOX *temp = (EFI_IFR_CHECKBOX*)&buffer[j];

                // Display temp
                if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
									            subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
              	{
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					VarTree.back().value.type = CHECK;
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
                    VarTree.back().value.obj.add(CHECKBOX, value);
					VarTree.back().value.val = value;
              	}
            }
			else if (buffer[j] == EFI_IFR_ACTION_OP) {

                // Create temp
                int value = 0;
                EFI_IFR_ACTION *temp = (EFI_IFR_ACTION*)&buffer[j];

                // Display temp
                if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
									            subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
              	{
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
                    VarTree.back().value.obj.add(ACTION, value);
              	}
            }
			else if (buffer[j] == EFI_IFR_REF_OP) {

                // Create temp
                EFI_IFR_REF *temp = (EFI_IFR_REF*)&buffer[j];
			   TreeInfo *TempForm = 0;
                if ((NULL != Form) && (bdisplay))
              	{
					uint16_t FormId = Form->value.FormId;
					string name = Form->value.name;
					TreeInfo tempTree = {0};
					
					tempTree.father = 0;
					tempTree.child = 0;
					tempTree.value.name = GetString(strings, temp->Question.Header.Prompt + strPackageOffset);
					tempTree.value.FormId = temp->FormId;
					TempForm = FindForm(FormTree,tempTree.value.FormId, tempTree.value.name);
					if (!TempForm)
					{
						FormTree.push_back(tempTree);
						if (FormTree[Tid].value.FormId == FormId)
						{
							Form = &FormTree[Tid];
						}
						else
						{
							Form = NULL;
						}
					}
				
			}
		}
            else if (buffer[j] == EFI_IFR_NUMERIC_OP) {

                // Create temp
                uint32_t value = 0;
                EFI_IFR_NUMERIC *temp = (EFI_IFR_NUMERIC*)&buffer[j];

				if ((NULL != Form) && bdisplay && ParisVaild ((EFI_IFR_NUMERIC*)&buffer[j]) && 
						QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
										subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset,VarMap, &variabletemp, inVarFile))
				{
					char buf[64];
					if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_1) {
						GetValueRange (&VarTree.back().value, temp->data.u8.MinValue, temp->data.u8.MaxValue, sizeof(buf), buf);
						value = (uint32_t)GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);

					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_2) {
						GetValueRange (&VarTree.back().value, temp->data.u16.MinValue, temp->data.u16.MaxValue, sizeof(buf), buf);
						value = (uint32_t)GetValue(2, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_4) {
						GetValueRange (&VarTree.back().value, temp->data.u32.MinValue, temp->data.u32.MaxValue, sizeof(buf), buf);
						value = (uint32_t)GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					}
					else if ((temp->Flags & EFI_IFR_NUMERIC_SIZE) == EFI_IFR_NUMERIC_SIZE_8) {
						GetValueRange (&VarTree.back().value, temp->data.u64.MinValue, temp->data.u64.MaxValue, sizeof(buf), buf);
						value = (uint32_t)GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 4, &VarTree.back().value.size);
						VarTree.back().value.obj.add(VALUE_H, value);
						VarTree.back().value.val = (value << 32);
						value = (uint32_t)GetValue(4, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
						VarTree.back().value.size = 8;
					}

					stringtest = buf;
					VarTree.back().value.type = NUM;
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
					VarTree.back().value.obj.add(VALUE_L, value);
					VarTree.back().value.obj.add(TIP, stringtest);
					//VarTree.back().value.obj.add("offset", VarTree.back().value.offset);
					VarTree.back().value.val |= value;
					stringtest.clear();
				}

            }
#if 0
            else if (buffer[j] == EFI_IFR_PASSWORD_OP) {

                // Create temp
                char buf[64];
								char *tempbuf = NULL;
								string tempstr;
                EFI_IFR_PASSWORD *temp = (EFI_IFR_PASSWORD*)&buffer[j];

                // Display temp
                if (QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &tempTree, 
									               subTree, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
								{
										snprintf(buf, sizeof(buf), "MinSize: %0d, MaxSize:%0d", temp->MinSize, temp->MaxSize);
										stringtest = buf;
										tempbuf = GetVarString (temp->MaxSize, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
										if (NULL != tempbuf)
										{
												tempstr = tempbuf;
												free(tempbuf);
												VarTree.back().value.obj.add(VALUE_L, tempstr);
										}

										VarTree.back().value.type = str;
										VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
										VarTree.back().value.obj.add(TIP, stringtest);
		            }
            }
#endif
            else if (buffer[j] == EFI_IFR_ONE_OF_OPTION_OP) {

                // Create temp
                 char buf[64];
                EFI_IFR_ONE_OF_OPTION *temp = (EFI_IFR_ONE_OF_OPTION*)&buffer[j];

                // Display temp
                snprintf(buf, sizeof(buf), " %s, Value:", GetString(strings, temp->Option + strPackageOffset));
                if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_8)
				{
					snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%d;", temp->Value.u8);

					/*  如果size不为0，证明这个选项没被屏蔽，才需要添加所以选项值 */
					if (stringtest.size() != 0)
						VarTree.back().value.valoption.push_back((uint64_t)temp->Value.u8);
				}
                else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_16)
				{
					snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%d;", temp->Value.u16);
					if (stringtest.size() != 0)
						VarTree.back().value.valoption.push_back((uint64_t)temp->Value.u16);
				}
                else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_32)
				{
					snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%d;", temp->Value.u32);
					if (stringtest.size() != 0)
						VarTree.back().value.valoption.push_back((uint64_t)temp->Value.u32);
				}
                else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_64)
				{
					snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%lld;", temp->Value.u64);
					if (stringtest.size() != 0)
						VarTree.back().value.valoption.push_back((uint64_t)temp->Value.u64);
				}
                    
                else if (temp->Type == EFI_IFR_TYPE_BOOLEAN)
				{
					snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s;", temp->Value.b ? "true" : "false");
					if (stringtest.size() != 0)
						VarTree.back().value.valoption.push_back((uint64_t)temp->Value.b);
				}
                    
                else if (temp->Type == EFI_IFR_TYPE_STRING)
                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s;", GetString(strings, temp->Value.string + strPackageOffset)); 

				if (stringtest.size() != 0)
				{
					stringtest += buf;
				}
            }
			else if (buffer[j] == EFI_IFR_DISABLE_IF_OP) {

				/* 禁能项不显示 */
				question = false;
				eql = false;
				valueIndex = 0;
				u8statusIndex = 0;
				if (bdisplay)
				{
					DisableIfCount = 0;
					bdisplay = false;
					bdiable = true;
				}
				else
				{
					if (bSuppress)
					{
						SuppressIfCount++;
					}
					
					DisableIfCount++;
					
				}			    
            }
			else if (buffer[j] == EFI_IFR_SUPPRESS_IF_OP) {
				question = false;
				eql = false;
				valueIndex = 0;
				u8statusIndex = 0;

				if (bdisplay)
				{
					bSuppress = true;
					SuppressIfCount = 0;
				}
				else
				{
					if (bdiable)
					{
						DisableIfCount++;
					}

					SuppressIfCount++;
					
				}
            }
			else if (buffer[j] == EFI_IFR_GRAY_OUT_IF_OP) {

				question = false;
				eql = false;
				valueIndex = 0;
				u8statusIndex = 0;
                if (bdiable)
				{
					DisableIfCount++;
				}

				if (bSuppress)
				{
					SuppressIfCount++;
				}
            }
			else if (buffer[j] == EFI_IFR_EQ_ID_VAL_LIST_OP) {

                // Create temp
                EFI_IFR_EQ_ID_VAL_LIST *temp = (EFI_IFR_EQ_ID_VAL_LIST*)&buffer[j];

                // Display temp
                for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == temp->QuestionId))
					{
						for (uint8_t k = 0; k < temp->ListLength; k++) {
							if (temp->ValueList[k]  == Qid[indexid].value)
							{
								bdisplay = false;
								break;
							}
						}
						question = true;
						break;
					}
				}
            }
			else if (buffer[j] == EFI_IFR_QUESTION_REF1_OP) {

                // Create temp
                EFI_IFR_QUESTION_REF1 *temp = (EFI_IFR_QUESTION_REF1*)&buffer[j];

				refqId = temp->QuestionId;
            }
			else if (buffer[j] == EFI_IFR_GREATER_THAN_OP) {

                // Create temp
                EFI_IFR_GREATER_THAN *temp = (EFI_IFR_GREATER_THAN*)&buffer[j];

				for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == refqId))
					{
						if (Qid[indexid].value > refqValue)
						{
							bdisplay = false;
						}

						if (u8statusIndex > 0)
						{
							bdisplay = bdisplay & bstatus;
							u8statusIndex = 0;
						}
							
						question = true;
						break;
					}
				}

				refqId = 0x0;

            }
            else if (buffer[j] == EFI_IFR_GREATER_EQUAL_OP) {

                // Create temp
                EFI_IFR_GREATER_EQUAL *temp = (EFI_IFR_GREATER_EQUAL*)&buffer[j];

                for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == refqId))
					{
						if (Qid[indexid].value >= refqValue)
						{
							bdisplay = false;
						}

						if (u8statusIndex > 0)
						{
							bdisplay = bdisplay & bstatus;
							u8statusIndex = 0;
						}
						question = true;
						break;
					}
				}

				refqId = 0x0;
            }
            else if (buffer[j] == EFI_IFR_LESS_THAN_OP) {

                // Create temp
                EFI_IFR_LESS_THAN *temp = (EFI_IFR_LESS_THAN*)&buffer[j];

                for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == refqId))
					{
						if (Qid[indexid].value < refqValue)
						{
							bdisplay = false;
						}

						if (u8statusIndex > 0)
						{
							bdisplay = bdisplay & bstatus;
							u8statusIndex = 0;
						}
						question = true;
						break;
					}
				}

				refqId = 0x0;
            }
			else if (buffer[j] == EFI_IFR_LESS_EQUAL_OP) {

                // Create temp
                EFI_IFR_LESS_EQUAL *temp = (EFI_IFR_LESS_EQUAL*)&buffer[j];
				for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == refqId))
					{
						if (Qid[indexid].value <= refqValue)
						{
							bdisplay = false;
						}

						if (u8statusIndex > 0)
						{
							bdisplay = bdisplay & bstatus;
							u8statusIndex = 0;
						}

						question = true;
						break;
					}
				}

				refqId = 0x0;
            }
			else if (buffer[j] == EFI_IFR_EQ_ID_VAL_OP) {

                // Create temp
                EFI_IFR_EQ_ID_VAL *temp = (EFI_IFR_EQ_ID_VAL*)&buffer[j];
				for (uint16_t indexid = 0; indexid < Qid.size(); indexid++)
				{
					if  ((bSuppress) && (FormSetname == Qid[indexid].name) && (SuppressIfCount == 0) && (Qid[indexid].Id == temp->QuestionId))
					{
						if (Qid[indexid].value == temp->Value)
						{
							bdisplay = false;
						}

						if (u8statusIndex > 0)
						{
							bdisplay = bdisplay & bstatus;
							u8statusIndex = 0;
						}

						question = true;
						break;
					}
				}
            }
			else if (buffer[j] == EFI_IFR_EQ_ID_ID_OP) {

                // Create temp
                EFI_IFR_EQ_ID_ID *temp = (EFI_IFR_EQ_ID_ID*)&buffer[j];
				if ((SuppressIfCount == 0) && bSuppress)
              	{
					if (temp->QuestionId1 ==  temp->QuestionId2)
					{
						bdisplay = false;
					}
					
					question = true;
              	}
            }
			else if (buffer[j] == EFI_IFR_NOT_OP) {

                // Create temp
                if (question)
				{
					bdisplay = !bdisplay;
					question = false;
				}
            }
			else if (buffer[j] == EFI_IFR_AND_OP) {

                // Create temp
                if (question)
				{
					bstatus = bdisplay;
					u8statusIndex = 1;
					bdisplay = true;
					question = false;
				}
            }
			else if (buffer[j] == EFI_IFR_EQUAL_OP) {

                if ((eql) && (value[0] != value[1]))
				{
					bdisplay = true;
				}

				eql = false;
            }
			else if (buffer[j] == EFI_IFR_NOT_EQUAL_OP) {

               if ((eql) && (value[0] == value[1]))
				{
					bdisplay = true;
				}

				eql = false;
            }

			/* ruguo1 */
			else if (buffer[j] == EFI_IFR_UINT8_OP) {

                // Create temp
                EFI_IFR_UINT8 *temp = (EFI_IFR_UINT8*)&buffer[j];

                if (valueIndex > 1)
				{
					valueIndex = 0;
				}

				refqValue = temp->Value;
				value[valueIndex] = temp->Value;
				valueIndex++;
                if ((0 == refqId) && (bdisplay) && (SuppressIfCount == 0) && bSuppress && (value[valueIndex - 1] > 0))
              	{
					bdisplay = false;
					eql = true;
              	}
            }
            else if (buffer[j] == EFI_IFR_UINT16_OP) {

                // Create temp
                EFI_IFR_UINT16 *temp = (EFI_IFR_UINT16*)&buffer[j];

				if (valueIndex > 1)
				{
					valueIndex = 0;
				}

				refqValue = temp->Value;
				value[valueIndex] = temp->Value;
				valueIndex++;
                if ((0 == refqId) && (bdisplay) && (SuppressIfCount == 0) && bSuppress && (value[valueIndex - 1] > 0))
              	{
					bdisplay = false;
					eql = true;
              	}
            }
            else if (buffer[j] == EFI_IFR_UINT32_OP) {

                // Create temp
                EFI_IFR_UINT32 *temp = (EFI_IFR_UINT32*)&buffer[j];

                if (valueIndex > 1)
				{
					valueIndex = 0;
				}

				refqValue = temp->Value;
				value[valueIndex] = temp->Value;
				valueIndex++;
                if ((0 == refqId) && (bdisplay) && (SuppressIfCount == 0) && bSuppress && (value[valueIndex - 1] > 0))
              	{
					bdisplay = false;
					eql = true;
              	}
            }
            else if (buffer[j] == EFI_IFR_UINT64_OP) {

                // Create temp
                EFI_IFR_UINT64 *temp = (EFI_IFR_UINT64*)&buffer[j];

                if (valueIndex > 1)
				{
					valueIndex = 0;
				}

				refqValue = temp->Value;
				value[valueIndex] = temp->Value;
				valueIndex++;
                if ((0 == refqId) && (bdisplay) && (SuppressIfCount == 0) && bSuppress && (value[valueIndex - 1] > 0))
              	{
					bdisplay = false;
					eql = true;
              	}
            }
			else if (buffer[j] == EFI_IFR_TRUE_OP) {

                if ((SuppressIfCount == 0) && bSuppress)
              	{
					bdisplay = false;
              	}
            }
#if 0
            else if (buffer[j] == EFI_IFR_DATE_OP) {

                // Create temp
                int value;
                EFI_IFR_DATE *temp = (EFI_IFR_DATE*)&buffer[j];

				if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
									            subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
              	{
					VarTree.back().value.type = DATE;
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
                    value = GetValue(2, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(YEAR, value);
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 2, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(MONTH, value);
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 3, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(DAY, value);
              	}
						
            }
            else if (buffer[j] == EFI_IFR_TIME_OP) {

                // Create temp
                int value;
                EFI_IFR_TIME *temp = (EFI_IFR_TIME*)&buffer[j];

				if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
									            subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
              	{
					VarTree.back().value.type = TIME;
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(HOUR, value);
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 1, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(MINUTE, value);
					value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + 2, &VarTree.back().value.size);
                    VarTree.back().value.obj.add(SECOND, value);
              	}

            }
#endif
            else if (buffer[j] == EFI_IFR_STRING_OP) {

                // Create temp
                char *tempbuf = NULL;
				char buf[64];
				string tempstr = "";
                EFI_IFR_STRING *temp = (EFI_IFR_STRING*)&buffer[j];

				if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0], 
									subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
				{
					snprintf(buf, sizeof(buf), "MinSize: %0d, MaxSize:%0d", temp->MinSize, temp->MaxSize);
					stringtest = buf;
					tempbuf = GetVarString (temp->MaxSize, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset, &VarTree.back().value.size);
					if (NULL != tempbuf)
					{
						tempstr = tempbuf;
						free(tempbuf);
					}

					VarTree.back().value.min = temp->MinSize;
					VarTree.back().value.max = temp->MaxSize;
					VarTree.back().value.type = STRING;
					VarTree.back().value.str = tempstr;
					VarTree.back().value.obj.add(VALUE_L, tempstr);
					VarTree.back().value.obj.add(TIP, stringtest);
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
					stringtest.clear();
				}
								
            }
            
            else if (buffer[j] == EFI_IFR_ORDERED_LIST_OP) {

                // Create temp
				JSONArray valuelist;
				int offset,value;
				char buf[64];
				
                EFI_IFR_ORDERED_LIST *temp = (EFI_IFR_ORDERED_LIST*)&buffer[j];
				
				if ((NULL != Form) && bdisplay && QuestionObjInt (VarTree, GetString(strings, temp->Question.Header.Prompt + strPackageOffset), &FormTree[0],
												subTree, Form, temp->Question.VarStoreId, temp->Question.VarStoreInfo.VarOffset, VarMap, &variabletemp, inVarFile))
				{
					for (offset = 0; offset < temp->MaxContainers; offset++)
					{
						value = GetValue(1, variabletemp.data.size, variabletemp.data.data, temp->Question.VarStoreInfo.VarOffset + offset, &VarTree.back().value.size);
						if (0 == value)
						{
							break;
						}
						
						valuelist.add((uint8_t)value);
					}

					snprintf(buf, sizeof(buf), "MaxContainers: %0d;", temp->MaxContainers);
					stringtest = buf;
					VarTree.back().value.type = LIST;
					startoption = OTHER;
					VarTree.back().value.obj.add(HELP, GetString(strings, temp->Question.Header.Help + strPackageOffset));
					VarTree.back().value.obj.add(LISTVAL, valuelist);
				}

            }
            else if (buffer[j] == EFI_IFR_VARSTORE_OP) {

                // Create temp	
				EFI_IFR_VARSTORE *temp = (EFI_IFR_VARSTORE*)&buffer[j];
				TreeInfo Vartemp;
				char   g_uuid_str[37] = { 0 };
			
				Vartemp.father = 0;
				Vartemp.child = 0;
				Vartemp.value.varFlag = true;
				convert_uuid_to_str (temp->Guid, g_uuid_str, sizeof(g_uuid_str));
				Vartemp.value.guid = g_uuid_str;
				Vartemp.value.name = (char *)temp->Name;
				Vartemp.value.VaribleId = temp->VarStoreId;
				subTree.push_back(Vartemp);
          	}
			else if (buffer[j] == EFI_IFR_VARSTORE_EFI_OP)
			{
				EFI_IFR_VARSTORE_EFI *temp = (EFI_IFR_VARSTORE_EFI*)&buffer[j];
				TreeInfo Vartemp;
				char   g_uuid_str[37] = { 0 };
			
				Vartemp.father = 0;
				Vartemp.child = 0;
				Vartemp.value.varFlag = true;
				convert_uuid_to_str (temp->Guid, g_uuid_str, sizeof(g_uuid_str));
				Vartemp.value.guid = g_uuid_str;
				Vartemp.value.name = (char *)temp->Name;
				Vartemp.value.VaribleId = temp->VarStoreId;
				subTree.push_back(Vartemp);
			}
			else if (buffer[j] == EFI_IFR_DEFAULT_OP) {

                // Create temp
                EFI_IFR_DEFAULT *temp = (EFI_IFR_DEFAULT*)&buffer[j];
				if (bAddItem)
				{
					if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_8)
                    	VarTree.back().value.defaultval = (uint16_t)temp->Value.u8;
					else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_16)
						VarTree.back().value.defaultval = temp->Value.u16;
					else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_32)
						VarTree.back().value.defaultval =  temp->Value.u32;
					else if (temp->Type == EFI_IFR_TYPE_NUM_SIZE_64)
						VarTree.back().value.defaultval = temp->Value.u64;
					else if (temp->Type == EFI_IFR_TYPE_BOOLEAN)
						VarTree.back().value.defaultval = temp->Value.b;
					else if (temp->Type == EFI_IFR_TYPE_STRING)
                    	VarTree.back().value.defaultstr = GetString(strings, temp->Value.string + strPackageOffset);

					if (NUM == VarTree.back().value.type)
					{
						/*if ((VarTree.back().value.val > VarTree.back().value.max) || 
						   (VarTree.back().value.val < VarTree.back().value.min))
						{
							VarTree.back().value.obj.add(VALUE_L, (int)(VarTree.back().value.defaultval));
						}*/
					}
					else
					{
						/*if ((VarTree.back().value.str.size()> VarTree.back().value.max) || 
						   (VarTree.back().value.str.size() < VarTree.back().value.min))
						{
							VarTree.back().value.obj.add(VALUE_L, VarTree.back().value.defaultstr);
						}*/
					}
				}
            
            }
           else if (buffer[j] == EFI_IFR_END_OP) {

                // Create temp
                EFI_IFR_END *temp = (EFI_IFR_END*)&buffer[j];
				refqId = 0x0;
                // Get condition
                uint8_t condition = conditionalStack.back();

                // Decrement conditional stack
                conditionalStack.pop_back();
                question = false;
				eql = false;
				if (startoption == condition)
				{
					if (stringtest.size() != 0)
					{
						VarTree.back().value.obj.add(TIP, stringtest);
					}

					bAddItem = false;
					stringtest.clear();
					startoption = 0xff;
				}

                if (condition == OPTION)
              	{
					
              	}
				else if (condition == FORM_SET)
				{
					subTree.clear();
              	}
				else if (condition == CONDITION)
				{
					valueIndex = 0;
					u8statusIndex = 0;
					if (0 == DisableIfCount)
					{
						bdiable = false;
					}
					
					if (bdiable)
					{
						DisableIfCount--;
					}

					if (0 == SuppressIfCount)
					{
						bSuppress = false;
					}
					
					if (bSuppress)
					{
						SuppressIfCount--;
					}

					if (!bSuppress && !bdiable)
					{
						bdisplay = true;
					}	
				}
                    
            }
           
            EFI_IFR_OP_HEADER *opHdr = (EFI_IFR_OP_HEADER*)&buffer[j];
            if (opHdr->Scope) {
                if (opHdr->OpCode == EFI_IFR_FORM_OP)
                    IndentText(FORM);
                else if (opHdr->OpCode == EFI_IFR_ONE_OF_OP)
                    IndentText(OPTION);
                else if (opHdr->OpCode == EFI_IFR_SUPPRESS_IF_OP || opHdr->OpCode == EFI_IFR_NO_SUBMIT_IF_OP || opHdr->OpCode == EFI_IFR_INCONSISTENT_IF_OP || opHdr->OpCode == EFI_IFR_GRAY_OUT_IF_OP || opHdr->OpCode == EFI_IFR_DISABLE_IF_OP || opHdr->OpCode == EFI_IFR_WARNING_IF_OP)
                    IndentText(CONDITION);
                else if (opHdr->OpCode == EFI_IFR_FORM_SET_OP)
                    IndentText(FORM_SET);
                else
                    IndentText(OTHER);
            }
        }
    }

void VarConfig :: generateUEFIIFRDump(const string &outputFile, const vector<UEFI_IFR_STRING_PACK> &stringPackages, const vector<UEFI_IFR_FORM_SET_PACK> &formSets, const string &buffer, const vector<string> &strings, map<int, vector<EFI_VARIABLE_PACK>> &VarMap, vector<string> inVarFile) {

	
	uint32_t Tid, id;
	vector<TreeInfo> FormTree;
	string FormSetname;
	bool firstform = false;

    subTree.clear();
	stringtest.clear();
	getinvaildId(Qid, stringPackages, formSets, buffer, strings, VarMap);
    // Go through form sets
    for (uint32_t i = 0; i < formSets.size(); i++) {

        uint32_t strPackageOffset = stringPackages[formSets[i].usingStringPackage].structureOffset;
        

        // Go through all the form set's operations
        for (uint32_t j = formSets[i].header.offset + 4; j < formSets[i].header.offset + formSets[i].header.length; j += static_cast<unsigned char>(buffer[j + 1]) & 0x7F) {
            /*if (buffer[j] == EFI_IFR_END_OP) {
                // Decrement number of tabs
                numberOfTabs--;
            }*/
            // Check opcodes
			if (!(static_cast<unsigned char>(buffer[j + 1]) & 0x7F))
			{
				break;
			}

            if (buffer[j] == EFI_IFR_FORM_SET_OP) {
                EFI_IFR_FORM_SET *temp = (EFI_IFR_FORM_SET*)&buffer[j];
				TreeInfo tempTree = {0};
				FormTree.clear();		
				tempTree.father = 1;
				tempTree.child = 0;
				firstform = false;
                tempTree.value.name = GetString(strings, temp->FormSetTitle + strPackageOffset);
				FormSetname = GetString(strings, temp->FormSetTitle + strPackageOffset);
				if (0 != tempTree.value.name.size())
				{
					/* 青松项目为了避免显示多余内容，只显示Setup下的内容 */
					//if (tempTree.value.name == "Setup")
					{
						FormTree.push_back(tempTree);
						firstform = true;
					}
				}
            }

            else if (buffer[j] == EFI_IFR_FORM_OP) {

                // Create temp
                string name;
				TreeInfo tempTree = {0};
                EFI_IFR_FORM *temp = (EFI_IFR_FORM*)&buffer[j];
				tempTree.father = 0;
				tempTree.child = 0;
				tempTree.value.name = GetString(strings, temp->FormTitle + strPackageOffset);
				name = tempTree.value.name;
				tempTree.value.FormId = temp->FormId;
				if (0 != name.size())
				{
					if (firstform)
					{
						FormTree.push_back(tempTree);
						firstform = false;
					}

					for (Tid = 1; Tid < FormTree.size(); Tid++)
					{
						FindFormTitle(i,Tid, FormTree, FormSetname, stringPackages, formSets, buffer, strings, VarMap, inVarFile);
					}
					
					break;
				}
            }
		}
    }
}
extern  std::string myu16stringToUtf8(std::u16string wstr);
int UCSToUTF(CHAR16 *szUCSBuf, string &CUtf8)
{
	std::u16string ws = szUCSBuf;
	
				
	CUtf8 = myu16stringToUtf8(ws);

	return 0;
}

int VarGuidGet(const vector<EFI_VARIABLE_PACK> &variablePackages, string CVarName, string &Guid)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr; 

	for (index = 0; index < variablePackages.size(); index++)
	{

		/* 变量中的状态为3F，证明这个变量有效 */
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}

								
		temstr=buf;
		if ((!temstr.compare(0, CVarName.size(), CVarName)) && (temstr.size() == CVarName.size()))
		{
			Guid = variablePackages[index].variableHeader.VendorGuid;
			return 0;
		}
	}

	return -1;
}

int VarInfoGetPtr_Guid(vector<EFI_VARIABLE_PACK> &variablePackages, string CVarName, string Guid, VARIABLE_PACK **pstVar)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr; 

	for (index = 0; index < variablePackages.size(); index++)
	{

		/* 变量中的状态为3F，证明这个变量有效 */
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		if (Guid != variablePackages[index].variableHeader.VendorGuid)
		{
			continue;
		}

		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}

								
		temstr=buf;
		if ((!temstr.compare(0, CVarName.size(), CVarName)) && (temstr.size() == CVarName.size()))
		{
			*pstVar = &variablePackages[index].variable;
			return 0;
		}
	}

	return -1;
}

int VarInfoGetPtr(vector<EFI_VARIABLE_PACK> &variablePackages, string CVarName, VARIABLE_PACK **pstVar)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr; 

	for (index = 0; index < variablePackages.size(); index++)
	{

		/* 变量中的状态为3F，证明这个变量有效 */
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}

								
		temstr=buf;
		if ((!temstr.compare(0, CVarName.size(), CVarName)) && (temstr.size() == CVarName.size()))
		{
			*pstVar = &variablePackages[index].variable;
			return 0;
		}
	}

	return -1;
}

int VarInfoGet(const vector<EFI_VARIABLE_PACK> &variablePackages, string CVarName, VARIABLE_PACK *pstVar)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr; 

	for (index = 0; index < variablePackages.size(); index++)
	{

		/* 变量中的状态为3F，证明这个变量有效 */
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}

								
		temstr=buf;
		if ((!temstr.compare(0, CVarName.size(), CVarName)) && (temstr.size() == CVarName.size()))
		{
			*pstVar = variablePackages[index].variable;
			return 0;
		}
	}

	return -1;
}

int VarConfig :: DevicePathParse(uint8_t *pDevicePath, uint64_t len, BootInfo *pstBootInfo)
{
	uint64_t index = 0;
	EFIDP *pstHeader = NULL;
	EFIDP_SATA *pstSata = NULL;
	EFIDP_NVME *pstNvme = NULL;

	while (index < len)
	{
		pstHeader = (EFIDP *)(pDevicePath + index);
		if (0x7f == pstHeader->type)
		{
			break;
		}
		else if (EFIDP_MESSAGE_TYPE == pstHeader->type)
		{
			if (EFIDP_MSG_SATA == pstHeader->subtype)
			{
				pstSata = (EFIDP_SATA *)pstHeader;
				pstBootInfo->u16SataId = pstSata->hba_port + 1;
				break;
			}
			else if (EFIDP_MSG_NVME == pstHeader->subtype)
			{
				pstNvme = (EFIDP_NVME *)pstHeader;
				pstBootInfo->u32NvmeId = pstNvme->namespace_id + 1;
				break;
			}
		}

		index += pstHeader->length;
	}

	return 0;
	
}

int  VarConfig:: InitSingleBootList(const string &InputFile)
{
    std::map<std::string, uint8_t> bootsinglemap;
	std::string tmpstr;
	std::string input = InputFile;

	bootsinglemap["hdd"]=0x10;
	bootsinglemap["cdrom"]=0x20;
	bootsinglemap["usbfloppy"]=0x30;
	bootsinglemap["usbkey"]=0x40;
	bootsinglemap["usbhdd"]=0x50;
	bootsinglemap["usbcdrom"]=0x60;
	bootsinglemap["lan"]=0x70;
	bootsinglemap["fv"]=0x80;
	bootsinglemap["nvme"]=0x90;
	bootsinglemap["pcie"]=0xa0;

	size_t pos = input.find('='); // 找到=号的位置
    if (pos != std::string::npos) {
        std::string substr = input.substr(pos + 1); // 提取=号后面的内容
        size_t comma_pos = substr.find(',');
        while (comma_pos != std::string::npos) {
            //std::cout << substr.substr(0, comma_pos) << std::endl;
            tmpstr = substr.substr(0, comma_pos);
            //std::cout<<tmpstr<<std::endl;
            auto itrtmp =  bootsinglemap.find(tmpstr);
            if(itrtmp != bootsinglemap.end() )
            {
                //std::cout<<std::hex<< itrtmp->second <<std::endl;
                //printf("test--%02X--\n",itrtmp->second);
                singlelist.insert(std::pair<uint8_t,std::string>(itrtmp->second,itrtmp->first));
            }
            //std::cout<< itrtmp <<std::endl;
            substr = substr.substr(comma_pos + 1);
            comma_pos = substr.find(',');
        }
        //std::cout << substr << std::endl; // 输出最后一个元素
        auto itrtmp =  bootsinglemap.find(substr);
        if(itrtmp != bootsinglemap.end() )
        {
                //std::cout<<std::hex<< itrtmp->second <<std::endl;
                //printf("test--%02X--\n",itrtmp->second);
                singlelist.insert(std::pair<uint8_t,std::string>(itrtmp->second,itrtmp->first));
        }

    }
	return 0;
}
int VarConfig::IsInSingleList(uint8_t BootID)
{
	
	return singlelist.count(BootID);
}

int VarConfig :: SetFirstBootModify(string FirstBoot,VARIABLE_PACK *pstBootOrder)
{
	uint32_t u32Num = 0;
	uint32_t i = 0;
	uint8_t *pu8data;
	bool bFind = false;
	vector<BootOrder> BootOrderList;
	vector<uint8_t> bootdata;
	BootOrder BootOrderTmp;
	uint8_t tmpdata = 0;
	uint8_t NameIndex = 0;

	const char  *OrdetlistName[] = {
		"hdd",
		"cdrom",
		"usbfloppy",
		"usbkey",
		"usbhdd",
		"usbcdrom",
		"lan",
		"fv",
		"nvme",
		"pcie"
	};

	u32Num = pstBootOrder->data.size;
	pu8data = (uint8_t *)&pstBootOrder->data.data[0];
	BootOrderList.clear();

	/* 由于设置首选项后，当前首选项和更新后首选项的顺序要调换，所以先要获取目前要设置项位置前的所有启动顺序 */
	for (i = 0; i < u32Num; i++)
	{
		memset(&BootOrderTmp, 0, sizeof(BootOrderTmp));
		if (pu8data[i] == 0)
		{
			break;
		}

		/* 如果是同组类型的，需要一起调整 */
		if (tmpdata == (pu8data[i] & 0xF0))
		{
			BootOrderList.back().au8value[BootOrderList.back().u8size] = pu8data[i];
			BootOrderList.back().u8size++;
			continue;
		}

		/* 如果已经找到首选项则退出 */
		if ((BootOrderList.size()) && (BootOrderList.back().name ==  FirstBoot))
		{
			/* 已经是首选项了，直接返回 */
			if (BootOrderList.size() == 1)
			{
				printf(" %s is already first boot. \n", FirstBoot.c_str());
				return 0;
			}

			printf("find boot %s \n", FirstBoot.c_str());
			bFind = true;
			break;
		}	

		if (BBS_OEM_OTHER == pu8data[i])
		{
			BootOrderTmp.u32offset = i;
			BootOrderTmp.name = "other";
			BootOrderTmp.au8value[0] = pu8data[i];
			BootOrderTmp.u8size = 1;
			BootOrderList.push_back(BootOrderTmp);
			tmpdata = 0;
			continue;
		}

		NameIndex =((pu8data[i] >> 4) - 1);
		if ((NameIndex + 1) > sizeof(OrdetlistName))
		{
			printf("boot %x is invalid.\n", pu8data[i]);
			return 1;
		}

		//if (  IsInSingleList(pu8data[i] & 0xF0) )
		if((BBS_OEM_HARDDISK == (pu8data[i] & 0xF0)) || (BBS_OEM_M2 == (pu8data[i] & 0xF0)) || (BBS_OEM_PCIE_STORAGE == (pu8data[i] & 0xF0)))
		{
			BootOrderTmp.u32offset = i;
			string tmp = std::string(OrdetlistName[NameIndex]) + std::to_string((pu8data[i] & 0x0F));
			BootOrderTmp.name = tmp;
			BootOrderTmp.au8value[0] = pu8data[i];
			BootOrderTmp.u8size = 1;
			BootOrderList.push_back(BootOrderTmp);
			tmpdata = 0;
			
			continue;
		}

		
		tmpdata = (pu8data[i] & 0xF0);
		BootOrderTmp.u32offset = i;
		string tmp = std::string(OrdetlistName[NameIndex]);
		BootOrderTmp.name = tmp ;
		BootOrderTmp.au8value[0] = pu8data[i];
		BootOrderTmp.u8size = 1;
		BootOrderList.push_back(BootOrderTmp);
		
	}

	if (!bFind)
	{
		printf("not find boot %s.\n", FirstBoot.c_str());
		return 1;
	}

	bootdata.clear();

	/* 最后一项为要设置的首选项 */
	for (i = 0; i < BootOrderList.back().u8size; i++)
	{
		bootdata.push_back(BootOrderList.back().au8value[i]);
	}

	for (i = 1; i < BootOrderList.size() - 1; i++)
	{
		for (uint8_t j = 0; j < BootOrderList[i].u8size; j++)
		{
			bootdata.push_back(BootOrderList[i].au8value[j]);
		}
	}

	/* 当前的首选项则放到最后一项 */
	for (i = 0; i < BootOrderList.front().u8size; i++)
	{
		bootdata.push_back(BootOrderList.front().au8value[i]);
	}

	for (i = 0; i < bootdata.size(); i++)
	{
		pu8data[i] = bootdata[i];
	}
	return 0;
}

int VarConfig ::FixVar(string VarCfg, map<int, vector<EFI_VARIABLE_PACK>> &VarMap)
{
	char guid[37] = {0};
	char name[128] = {0};
	char tmpBuf[64] = {0};
	char str[128] = {0};
	uint32_t u32offset;
	uint32_t u32len;
	uint32_t u32Val;
	uint32_t i = 0;
	uint8_t *pu8data = NULL;
	VARIABLE_PACK *pstVar = NULL;

	bool bFound = false;

	sscanf(VarCfg.c_str(), FIXVAR, name, guid, &u32offset, tmpBuf);
	if (strncmp(tmpBuf,	"str", 3) == 0)
	{
		sscanf(tmpBuf, "%*[^:]:%x:%s", &u32len, str);
		//printf("name %s guid %s offset %x len %x str %s\r\n", name, guid, u32offset, u32len, str);
	}
	else
	{
		sscanf(tmpBuf, "%x:%x", &u32len, &u32Val);
		//printf("name %s guid %s offset %x u32len %x val %x\r\n", name, guid, u32offset, u32len, u32Val);
	}
	
	for (i = 0; i < VarMap.size(); i++)
	{
		if (VarInfoGetPtr_Guid(VarMap[i], name, guid, &pstVar) == 0)
		{
			pu8data = &pstVar->data.data[0];

			if (strlen(str))
			{
				memset(pu8data + u32offset, 0, u32len);
				memcpy(pu8data + u32offset, str, strlen(str));
			}
			else
			{
				memcpy(pu8data + u32offset, &u32Val, u32len);
			}

			bFound = true;
		} 
	}

	if (bFound)
	{
		return 0;
	}

	return 1;
	
}

int VarConfig :: SetFirstBoot(int mode, string FirstBoot, map<int, vector<EFI_VARIABLE_PACK>> &variableMap)
{
	uint32_t i = 0;
	string  CBootOrder;
	VARIABLE_PACK *pstBootOrder = NULL;
	uint32_t u32Num = 0;
	uint8_t *pu8data;
	uint8_t NameIndex = 0;
	uint8_t tmpdata = 0;
	vector<BootOrder> BootOrderList;
	vector<uint8_t> bootdata;
	BootOrder BootOrderTmp;
	const char  *OrdetlistName[] = {
		"hdd",
		"cdrom",
		"usbfloppy",
		"usbkey",
		"usbhdd",
		"usbcdrom",
		"lan",
		"fv",
		"nvme",
		"pcie"
	};

	/* 0为工厂模式 */
	if (mode)
	{
		CBootOrder = PrimaryBootVar;
	}
	else
	{
		CBootOrder = ManuFacBootVar;
	}

	for (i = 0; i < variableMap.size(); i++)
	{
		if (VarInfoGetPtr(variableMap[i], CBootOrder, &pstBootOrder) == 0)
		{
			//break;
			if(SetFirstBootModify(FirstBoot, pstBootOrder) == 1)
			{
				cout << "FirstBootModify Not Found Var" << CBootOrder << endl;
				//return 1;
			}
		}
	}
#if 0
	if (i == variableMap.size())
	{
		cout << "Not Found Var" << CBootOrder << endl;
		return 1;
	}
#endif
#if 0
	u32Num = pstBootOrder->data.size;
	pu8data = (uint8_t *)&pstBootOrder->data.data[0];
	BootOrderList.clear();

	/* 由于设置首选项后，当前首选项和更新后首选项的顺序要调换，所以先要获取目前要设置项位置前的所有启动顺序 */
	for (i = 0; i < u32Num; i++)
	{
		memset(&BootOrderTmp, 0, sizeof(BootOrderTmp));
		if (pu8data[i] == 0)
		{
			break;
		}	

		if (BBS_OEM_OTHER == pu8data[i])
		{
			BootOrderTmp.u32offset = i;
			BootOrderTmp.name = "other";
			BootOrderTmp.au8value[0] = pu8data[i];
			BootOrderTmp.u8size = 1;
			BootOrderList.push_back(BootOrderTmp);
			tmpdata = 0;
			continue;
		}

		NameIndex =((pu8data[i] >> 4) - 1);
		if ((NameIndex + 1) > sizeof(OrdetlistName))
		{
			printf("boot %x is invalid.\n", pu8data[i]);
			return 1;
		}

		if ((BBS_OEM_HARDDISK == (pu8data[i] & 0xF0)) || (BBS_OEM_M2 == (pu8data[i] & 0xF0)) || (BBS_OEM_PCIE_STORAGE == (pu8data[i] & 0xF0)) )
		{
			if ((BootOrderList.size()) && (BootOrderList.back().name ==  FirstBoot))
			{
				/* 已经是首选项了，直接返回 */
				if (BootOrderList.size() == 1)
				{
					printf(" %s is already first boot. \n", FirstBoot.c_str());
					return 0;
				}

				printf("find boot %s \n", FirstBoot.c_str());
				break;
			}

			BootOrderTmp.u32offset = i;
			string tmp = std::string(OrdetlistName[NameIndex]) + std::to_string((pu8data[i] & 0x0F));
			BootOrderTmp.name = tmp;
			BootOrderTmp.au8value[0] = pu8data[i];
			BootOrderTmp.u8size = 1;
			BootOrderList.push_back(BootOrderTmp);
			tmpdata = 0;
			
			continue;
		}

		if (tmpdata == (pu8data[i] & 0xF0))
		{
			BootOrderList.back().au8value[BootOrderList.back().u8size] = pu8data[i];
			BootOrderList.back().u8size++;
			continue;
		}
		else
		{
			if ((BootOrderList.size()) && (BootOrderList.back().name ==  FirstBoot))
			{
				/* 已经是首选项了，直接返回 */
				if (BootOrderList.size() == 1)
				{
					printf(" %s is already first boot. \n", FirstBoot.c_str());
					return 0;
				}

				printf("find boot %s \n", FirstBoot.c_str());
				break;
			}

			tmpdata = (pu8data[i] & 0xF0);
			BootOrderTmp.u32offset = i;
			string tmp = std::string(OrdetlistName[NameIndex]);
			BootOrderTmp.name = tmp ;
			BootOrderTmp.au8value[0] = pu8data[i];
			BootOrderTmp.u8size = 1;
			BootOrderList.push_back(BootOrderTmp);
		}
	}

	if ((i == u32Num) || (pu8data[i] == 0))
	{
		printf("not find boot %s.\n", FirstBoot.c_str());
		return 1;
	}

	bootdata.clear();

	/* 最后一项为要设置的首选项 */
	for (i = 0; i < BootOrderList.back().u8size; i++)
	{
		bootdata.push_back(BootOrderList.back().au8value[i]);
	}

	for (i = 1; i < BootOrderList.size() - 1; i++)
	{
		for (uint8_t j = 0; j < BootOrderList[i].u8size; j++)
		{
			bootdata.push_back(BootOrderList[i].au8value[j]);
		}
	}

	/* 当前的首选项则放到最后一项 */
	for (i = 0; i < BootOrderList.front().u8size; i++)
	{
		bootdata.push_back(BootOrderList.front().au8value[i]);
	}

	for (i = 0; i < bootdata.size(); i++)
	{
		pu8data[i] = bootdata[i];
	}
#endif
	return 0;
}

int VariableDel(vector<EFI_VARIABLE_PACK> &variablePackages, string CVarName)
{
	uint32_t index = 0, i = 0;
	char buf[128] = {0};
	string temstr; 

	for (index = 0; index < variablePackages.size(); index++)
	{

		/* 变量中的状态为3F，证明这个变量有效 */
		if (variablePackages[index].variableHeader.State != 0x3f)
		{
			continue;
		}

		for (i = 0; i < variablePackages[index].variable.name.name.size(); i+=2)
		{
			buf[(i/2)] = *(variablePackages[index].variable.name.name.c_str() + i);
		}

								
		temstr=buf;
		if ((!temstr.compare(0, CVarName.size(), CVarName)) && (temstr.size() == CVarName.size()))
		{
			VARIABLE_HEADER *variableHeader = (VARIABLE_HEADER *)(variablePackages[index].data.data());
			AUTH_VARIABLE_HEADER *variableAuthHeader = (AUTH_VARIABLE_HEADER *)(variablePackages[index].data.data());
			if (variablePackages[index].variableHeader.NameSize == variableHeader->NameSize)
			{
				variableHeader->State = 0x3C;
			}
			else if (variablePackages[index].variableHeader.NameSize == variableAuthHeader->NameSize)
			{
				variableAuthHeader->State = 0x3C;
			}
			else
			{
				printf("%s not find suitable format", temstr.c_str());
				return -1;
			}

			return 0;
		}
	}

	return 1;
}

int VarConfig :: BootDefault(int mode, map<int, vector<EFI_VARIABLE_PACK>> &variableMap)
{
	string  CBootOrder = "BootOrder";
	uint32_t u32Num = 0, i = 0, u32VarIndex = 0;
	uint32_t u32VarDisableIndex=0;
	VARIABLE_PACK stBootOrder;
	VARIABLE_PACK stBootDisableOrder;
	uint16_t *pu16data = NULL;
	char tempname[1024]={0};

	string  CBootDisableOrder="";
	/* 0为工厂模式 */
	if (mode)
	{
		CBootOrder = PrimaryBootVar;
		CBootDisableOrder="PrimaryBootDisableOrder";

	}
	else
	{
		CBootOrder = ManuFacBootVar;
		CBootDisableOrder="ManufacturingBootDisableOrder";
	}

	for (i = 0; i < variableMap.size(); i++)
	{
		if (VarInfoGet(variableMap[i], CBootOrder, &stBootOrder) == 0)
		{
			u32VarIndex = i;
			VariableDel(variableMap[u32VarIndex], CBootOrder);
			//break;
		}
		if (VarInfoGet(variableMap[i], CBootDisableOrder, &stBootDisableOrder) == 0)
		{
			u32VarDisableIndex = i;
			VariableDel(variableMap[u32VarDisableIndex], CBootDisableOrder);
			//break;
		}

	}
	return 0;
#if 0
	if (i == variableMap.size())
	{
		cout << "Not Found Var" << CBootOrder << endl;
		return 1;
	}
#endif
	if(u32VarDisableIndex)
	{
		VariableDel(variableMap[u32VarDisableIndex], CBootDisableOrder);
	}
	if(u32VarIndex)
	{
		if (VariableDel(variableMap[u32VarIndex], CBootOrder))
		{
			return 1;
		}
	}


	return 0;
}

void VarConfig :: BootModeParse(int mode, map<int, vector<EFI_VARIABLE_PACK>> &variableMap)
{
	uint32_t u32Num = 0,i = 0, u32Index = 0, u32VarIndex = 0, u32min = 0xFFFF, u32max = 0;
	uint8_t *pu8data = NULL;
	uint8_t NameIndex = 0;
    char tempname[1024]={0};
	string CHelp = "Set the system Manufacturing boot order";    
	string CTip;          
	TreeInfo FormSet, stForm, stVarible, stconfig;
	string  CBootOrder = ManuFacBootVar;
	VARIABLE_PACK stBootOrder;
    vector<uint64_t> valoption;
	BootInfo BootInfoTmp;
	vector<BootInfo> BootInfoList;
	const char  *OrdetlistName[] = {
		"hdd",
		"cdrom",
		"usbfloppy",
		"usbkey",
		"usbhdd",
		"usbcdrom",
		"lan",
		"fv",
		"nvme",
		"pcie"
	};

	/* 0为工厂模式 */
	if (mode)
	{
		CBootOrder = PrimaryBootVar;
		CHelp = PrimaryHELP;
	}
	else
	{
		CBootOrder = ManuFacBootVar;
		CHelp = ManuFacHELP;
	}

	if (NULL != CfgJson)
	{
		int bbotorder = 0;
		bbotorder = CfgJson->get<int>(BOOTORDERSHOW);
		if (0 == bbotorder)
		{
			return;
		}
	}

	for (i = 0; i < variableMap.size(); i++)
	{
		if (VarInfoGet(variableMap[i], CBootOrder, &stBootOrder) == 0)
		{
			u32VarIndex = i;
			break;
		}
	}

	if (i == variableMap.size())
	{
		//cout << "Not Found Var" << CBootOrder << endl;
		return;
	}

	bBootOrder = true;
	
	FormSet.father = 1;
	FormSet.value.name = "Boot";
	FormSet.child = SerchSameName(VarTree, FormSet.father, FormSet.value.name);
	if (0 == FormSet.child)
	{
		FormSet.child = VarTree.size() + 2;
		VarTree.push_back(FormSet);
	}
	
	stForm.father = FormSet.child - 1;
	stForm.value.name = "Order";
	stForm.child = SerchSameName(VarTree, stForm.father, stForm.value.name);
	if (0 == stForm.child)
	{
		stForm.value.CfgFlag = true;
		stForm.child = VarTree.size() + 2;
		VarTree.push_back(stForm);
	}

	stVarible.father = stForm.child - 1;
	stVarible.child = VarTree.size() + 2;
	stVarible.value.name = CBootOrder;
	stVarible.value.varFlag = true;
	VarGuidGet(variableMap[u32VarIndex], CBootOrder, stVarible.value.guid);
	VarTree.push_back(stVarible);


	u32Num = stBootOrder.data.size ;
	pu8data = (uint8_t *)&stBootOrder.data.data[0];
	BootInfoList.clear();
	for (i = 0; i < u32Num; i++)
	{
		memset(&BootInfoTmp, 0, sizeof(BootInfoTmp));

		if (pu8data[i] == 0)
		{
			break;
		}

		BootInfoTmp.u16Index = pu8data[i];

		if (BBS_OEM_OTHER == pu8data[i])
		{
			BootInfoTmp.CDescription = "other";
		}
		else
		{
			NameIndex =((pu8data[i] >> 4) - 1);
			if ((NameIndex + 1) > sizeof(OrdetlistName))
			{
				printf("boot %x is invalid.\n", pu8data[i]);
				return ;
			}

			string tmp = std::string(OrdetlistName[NameIndex]) + std::to_string((pu8data[i] & 0x0F));
			BootInfoTmp.CDescription = tmp;
		}

		BootInfoList.push_back(BootInfoTmp);

		if (pu8data[i] < u32min)
		{
			u32min = pu8data[i];
		}

		if (pu8data[i] > u32max)
		{
			u32max = pu8data[i];
		}
	}

	snprintf(tempname, sizeof(tempname), "Min: %d, Max:%d; ", u32min, u32max);
	for (i = 0; i < BootInfoList.size(); i++)
	{
		snprintf(tempname + strlen(tempname), sizeof(tempname) - strlen(tempname), "%s, Value:%d; ", BootInfoList[i].CDescription.c_str(), BootInfoList[i].u16Index);
	}

	CTip = tempname;

	VarTree[FormSet.child - 2].value.bbootorder =  true;
	VarTree[stForm.child - 2].value.bbootorder =  true;
	VarTree[stVarible.child - 2].value.bbootorder =  true;

	for (i = 0; i < BootInfoList.size(); i++)
	{
		u32Index++;

		snprintf(tempname, sizeof(tempname), "Boot Option #%d", u32Index);
	    VarTree[stForm.child - 2].value.CfgList.add((string)tempname);
		stconfig.father = stVarible.child - 1;
		stconfig.child = 0;
		stconfig.value.max = u32max;
		stconfig.value.min = u32min;
		stconfig.value.name = tempname;
		stconfig.value.offset = i;
		stconfig.value.size = 1;
		stconfig.value.type = NUM;
		stconfig.value.val = BootInfoList[i].u16Index;
		stconfig.value.bbootorder = true;
		stconfig.value.obj.add(TIP, CTip);
		stconfig.value.obj.add(HELP, CHelp);
		stconfig.value.obj.add(VALUE_L, (unsigned int)BootInfoList[i].u16Index);
		VarTree.push_back(stconfig);
	}

	return ;

}

void VarConfig :: BootOrderParse(map<int, vector<EFI_VARIABLE_PACK>> &variableMap)
{
	uint32_t u32Num = 0,i = 0, u32Attributes = 0, u32Index = 0, u32min = 0xFFFF, u32max = 0, u32VarIndex = 0;
	uint16_t *pu16data = NULL;
	uint64_t u64Size = 0;
    char tempname[1024]={0};
	string CHelp = "Set the system boot order";    
	string CTip;          
	TreeInfo FormSet, stForm, stVarible, stconfig;
	string  CBootOrder = "BootOrder";
	VARIABLE_PACK stBootOrder;
    vector<uint64_t> valoption;
	BootInfo *pstBootInfo = NULL;

	if (bBootOrder)
	{
		return;
	}

	if (NULL != CfgJson)
	{
		int bbotorder = 0;
		bbotorder = CfgJson->get<int>(BOOTORDERSHOW);
		if (0 == bbotorder)
		{
			return;
		}
	}

	for (i = 0; i < variableMap.size(); i++)
	{
		if (VarInfoGet(variableMap[i], CBootOrder, &stBootOrder) == 0)
		{
			u32VarIndex = i;
			break;
		}
	}

	if (i == variableMap.size())
	{
		cout << "Not Found Var" << CBootOrder << endl;
		return;
	}
	
	FormSet.father = 1;
	FormSet.value.name = "Boot";
	FormSet.child = SerchSameName(VarTree, FormSet.father, FormSet.value.name);
	if (0 == FormSet.child)
	{
		FormSet.child = VarTree.size() + 2;
		VarTree.push_back(FormSet);
	}
	
	stForm.father = FormSet.child - 1;
	stForm.value.name = "Order";
	stForm.child = SerchSameName(VarTree, stForm.father, stForm.value.name);
	if (0 == stForm.child)
	{
		stForm.value.CfgFlag = true;
		stForm.child = VarTree.size() + 2;
		VarTree.push_back(stForm);
	}

	stVarible.father = stForm.child - 1;
	stVarible.child = VarTree.size() + 2;
	stVarible.value.name = CBootOrder;
	stVarible.value.varFlag = true;
	VarGuidGet(variableMap[u32VarIndex], CBootOrder, stVarible.value.guid);
	VarTree.push_back(stVarible);


	u32Num = stBootOrder.data.size / 2;
	pu16data = (uint16_t *)&stBootOrder.data.data[0];
    pstBootInfo = new BootInfo[u32Num];
	for (i = 0; i < u32Num; i++)
	{
		snprintf(tempname, sizeof(tempname), "Boot%04x", pu16data[i]);
		pstBootInfo[i].CName =  tempname;
		pstBootInfo[i].u16Index = pu16data[i];
		pstBootInfo[i].u16SataId = 0;
		pstBootInfo[i].u32NvmeId = 0;

		if (VarInfoGet(variableMap[u32VarIndex], pstBootInfo[i].CName, &pstBootInfo[i].stBootOrder) < 0)
		{
			//cout << "Not Found Var" << pstBootInfo[i].CName << endl;
			snprintf(tempname, sizeof(tempname), "Boot%04X", pu16data[i]);
			pstBootInfo[i].CName =  tempname;
			if (VarInfoGet(variableMap[u32VarIndex], pstBootInfo[i].CName, &pstBootInfo[i].stBootOrder) < 0)
			{
				cout << "Not Found Var" << pstBootInfo[i].CName << endl;
				return;
			}
		}

		u32Attributes = *((uint32_t *)&pstBootInfo[i].stBootOrder.data.data[0]);
		if (0 == (u32Attributes & 0x01))
		{
			continue;
		}

		if (UCSToUTF((CHAR16*)&pstBootInfo[i].stBootOrder.data.data[6], pstBootInfo[i].CDescription) < 0)
		{
			cout << "UCS to UTF8 " << pstBootInfo[i].CName << " Fail" << endl;
			return;
		}

		u64Size = (pstBootInfo[i].CDescription.length() + 1) * 2;

		DevicePathParse((uint8_t *)&pstBootInfo[i].stBootOrder.data.data[6 + u64Size], pstBootInfo[i].stBootOrder.data.size - u64Size, &pstBootInfo[i]);

		stconfig.value.valoption.push_back((uint64_t)pu16data[i]);

		if (pu16data[i] < u32min)
		{
			u32min = pu16data[i];
		}

		if (pu16data[i] > u32max)
		{
			u32max = pu16data[i];
		}

	}

	snprintf(tempname, sizeof(tempname), "Min: %d, Max:%d; ", u32min, u32max);
	for (i = 0; i < u32Num; i++)
	{
		u32Attributes = *((uint32_t *)&pstBootInfo[i].stBootOrder.data.data[0]);
		if (0 == (u32Attributes & 0x01))
		{
			continue;
		}

		if ((std::string::npos != pstBootInfo[i].CDescription.find("DVDRAM")) || (std::string::npos != pstBootInfo[i].CDescription.find("CDROM")))
		{
			snprintf(tempname + strlen(tempname), sizeof(tempname) - strlen(tempname), "%s, Value:%d; ", pstBootInfo[i].CDescription.c_str(), pstBootInfo[i].u16Index);
		}
		else if (0 != pstBootInfo[i].u16SataId)
		{
			snprintf(tempname + strlen(tempname), sizeof(tempname) - strlen(tempname), "%s SATA%d, Value:%d; ", pstBootInfo[i].CDescription.c_str(), pstBootInfo[i].u16SataId - 1, pstBootInfo[i].u16Index);
		}
		else if (0 != pstBootInfo[i].u32NvmeId)
		{
			snprintf(tempname + strlen(tempname), sizeof(tempname) - strlen(tempname), "%s NVME%d, Value:%d; ", pstBootInfo[i].CDescription.c_str(), pstBootInfo[i].u32NvmeId - 1, pstBootInfo[i].u16Index);
		}
		else
		{
			snprintf(tempname + strlen(tempname), sizeof(tempname) - strlen(tempname), "%s, Value:%d; ", pstBootInfo[i].CDescription.c_str(), pstBootInfo[i].u16Index);
		}
	}

	CTip = tempname;

	VarTree[FormSet.child - 2].value.bbootorder =  true;
	VarTree[stForm.child - 2].value.bbootorder =  true;
	VarTree[stVarible.child - 2].value.bbootorder =  true;

	for (i = 0; i < u32Num; i++)
	{
		u32Attributes = *((uint32_t *)&pstBootInfo[i].stBootOrder.data.data[0]);
		if (0 == (u32Attributes & 0x01))
		{
			continue;
		}

		u32Index++;

		if (1 == u32Index)
		{
			stconfig.value.firstBoot = true;
		}
		else
		{
			stconfig.value.firstBoot = false;
		}

		snprintf(tempname, sizeof(tempname), "Boot Option #%d", u32Index);
	    VarTree[stForm.child - 2].value.CfgList.add((string)tempname);
		stconfig.father = stVarible.child - 1;
		stconfig.child = 0;
		stconfig.value.max = u32max;
		stconfig.value.min = u32min;
		stconfig.value.name = tempname;
		stconfig.value.offset = i * 2;
		stconfig.value.size = 2;
		stconfig.value.type = NUM;
		stconfig.value.val = stBootOrder.data.data[i * 2];
		stconfig.value.bbootorder = true;
		stconfig.value.obj.add(TIP, CTip);
		stconfig.value.obj.add(HELP, CHelp);
		stconfig.value.obj.add(VALUE_L, (unsigned int)stBootOrder.data.data[i * 2]);
		VarTree.push_back(stconfig);
	}

}

void VarConfig :: ParseCfgFile(void)
{
	ifstream in(CFGFILE, std::ios::binary);
	streampos ps;
	string configstring;
	int FileSize = 0;
	char *buf = NULL;
	
	/* 打开配置文件获取配置内容 */
	in.seekg(0, ios::end);
	ps = in.tellg();
	FileSize = (int)ps;
	in.seekg(0, std::ios::beg);
	if (in.is_open())
	{
		buf = (char *)calloc(1, FileSize+1);

		in.read(buf, FileSize);
		configstring = buf;

		/* 获取内容的JSON结构 */
		CfgJson = dynamic_cast<JSONObject *>(JSONBase::parse(configstring));
		if (NULL == CfgJson || CfgJson->getSize() == 0)
		{
			cout<<CFGFILE<<" is null"<<endl;
			in.close();
			free(buf);
			return;
		}

		in.close();
	    free(buf);
	}
}

void VarConfig :: CreatFile(const string &outputFile, uint8_t u8Flag)
{
	ofstream fout(outputFile.c_str(), std::ios::binary);
	if (SHOW == u8Flag)
	{
		bShow = true;
	}
	if (BOOTEX == u8Flag)
		CreateBootOrderJson(0);
	else
		CreateJson (0);
	fout << VarTree[0].value.obj.toString(4) << endl;
	fout.close();
}

void VarConfig :: CfgFIleInit(vector<string> inVarFile)
{
	ofstream fout(CFGFILE, std::ios::binary);
	JSONArray CfgList;
	for (int i = 0; i < inVarFile.size(); i++)
	{
		CfgList.add((string)inVarFile[i]);
	}

	VarTree[0].value.obj.add(CFGVARFILE, CfgList);
	VarTree[0].value.obj.add(BOOTORDERSHOW, 1);
	CfgFileInitial(0);
	
	fout << VarTree[0].value.obj.toString(4) << endl;
	fout.close();
}

